<template>
  <div class="daai-tooltip" v-on="outerEvents">
    <!-- 触发元素,设置为一个插槽 -->
    <div class="daai-tooltip__trigger" ref="triggerRef" v-on="events">
      <slot></slot>
    </div>
    <!-- 提示内容元素，有时候比较复杂，所以用插槽，可以自己定义 -->
    <div class="daai-tooltip__popper" ref="popperRef" v-show="isOpen">
      <slot name="content">
        {{ content }}
      </slot>
      <!-- 箭头元素 -->
      <div id="arrow" data-popper-arrow></div>
    </div>
  </div>
</template>

<script setup>
import { createPopper } from '@popperjs/core'
import { reactive, ref, watch } from 'vue'
import { debounce } from 'lodash-es'
import propTypes from './props'
defineOptions({
  name: 'DaaiTooltip',
})
const props = defineProps(propTypes)

const isOpen = ref(false) // 是否显示tooltip

const triggerRef = ref(null) // 触发元素

const popperRef = ref(null) // 提示内容元素

const events = reactive({}) // 用于绑定事件
const outerEvents = reactive({})

const emit = defineEmits(['visible-change'])

const debounceOpen = debounce(() => {
  isOpen.value = true
  emit('visible-change', true)
}, props.openDelay)

const debounceClose = debounce(() => {
  isOpen.value = false
  emit('visible-change', false)
}, props.closeDelay)
const open = () => {
  debounceClose.cancel()
  debounceOpen()
}

const close = () => {
  debounceOpen.cancel()
  debounceClose()
}

// 创建popper实例
let popperInstance = null // 存储popper实例
// 创建popper配置项
const popperOptions = ref({
  placement: props.placement,
  modifiers: [
    {
      name: 'offset',
      options: {
        offset: [0, 6],
      },
    },
  ],
})

watch(
  isOpen,
  (newValue) => {
    if (newValue) {
      if (triggerRef.value && popperRef.value) {
        // 创建 popper 实例
        popperInstance = createPopper(triggerRef.value, popperRef.value, popperOptions.value)
      } else {
        popperInstance?.destroy()
      }
    }
  },
  { flush: 'post' }, // 设置dom渲染后运行
)

const attachEvents = () => {
  // 判断触发方式
  if (props.trigger === 'hover') {
    // 鼠标移入触发
    events['mouseenter'] = open
    outerEvents['mouseleave'] = close
  } else if (props.trigger === 'click') {
    // 点击触发
    events['click'] = () => {
      isOpen.value ? close() : open()
    }
  }
}

// 这里我们需要判断用户是否要自定义处理
// 只有在用户不需要自定义处理的时候，我们才绑定事件
if (!props.manual) {
  // 初始化绑定事件
  attachEvents()
}

// 暴露两个方法，用于给用户手动触发显示隐藏
defineExpose({
  show: open,
  hide: close,
})
</script>

<style lang="scss" scoped></style>
